/*
* Copyright (c) 2025 Shenzhen Kaihong Digital Industry Development Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const { XPlatform } = require("../XPlatform");
const { XTools } = require("../XTools");
const { PackageTool } = require("../../src/ros_msg_utils/PackageTool");

class WsClient {
    constructor(url, cb = null) {
        this.url_ = url;
        this.callback_ = cb;
        this.stat_ = false;
        this.async_ = {};
        this.func_ = {};
        this.userId_ = -1;
        this.userName_ = "";
        this.userToken_ = "";
        this.job_ = 10000;
        this.connect_();

        this.headBuffer = new ArrayBuffer(4);
        this.uint8Array = new Uint8Array(this.headBuffer);

        this.tmpBuffer = Buffer.alloc(1024 * 1024 * 10);
        this.pt = new PackageTool();
        this.pt.buffer = this.tmpBuffer;
    }

    send_(buffer, len) {
        if (!this.stat_) {
            return false;
        }
        this.uint8Array[0] = len
        this.uint8Array[1] = len >> 8;
        this.uint8Array[2] = len >> 16;
        this.uint8Array[3] = len >> 24;
        this.ws_.send(this.headBuffer);
        this.ws_.send(buffer.subarray(0, len));
    }
    connect_() {
        this.ws_ = new WebSocket(this.url_);
        this.ws_.binaryType = "arraybuffer";
        this.offset_ = 0;
        this.ws_.addEventListener('message', (msg) => {
            console.log("onMessage", msg.data.byteLength);
            // let t1 = Date.now()
            Buffer.from(msg.data).copy(this.tmpBuffer, this.offset_, 0, msg.data.byteLength);
            // this.tmpBuffer.write(msg.data, this.offset_, msg.data.length);
            this.offset_ += msg.data.byteLength;

            if (this.offset_ >= 4) {
                let msg_len = this.tmpBuffer.readUInt32LE(0);
                if (msg_len + 4 <= this.offset_) {
                    this.pt.buffer = this.tmpBuffer;
                    this.pt.offset = [4];
                    let protocol = this.pt.get_string();
                    if (protocol in this.func_) {
                        this.func_[protocol](this.pt);
                    }
                    if (msg_len + 4 < this.offset_) {
                        this.tmpBuffer.copy(this.tmpBuffer, 0, msg_len + 4, this.offset_);
                    }
                    this.offset_ -= msg_len + 4;
                    // console.log("procmsg:", protocol, "len:", msg_len);
                }
            }
            // console.log("recv cost:", Date.now() - t1)
        });

        this.ws_.addEventListener('error', (e) => {
            // GMessage.open("连接错误");
            this.stat_ = false;
        });
        this.ws_.addEventListener('open', (e) => {
            this.stat_ = true;
            const { RosProto } = require("../../src/ros_msg_utils/RosProto");
            RosProto.registProcess();
        });
        this.ws_.addEventListener('close', (e) => {
            // GMessage.open("连接关闭，稍后重试 new");
            this.stat_ = false;
            setTimeout(() => {
                this.connect_();
            }, 5000);
        });
    }
    static startConnect(addr) {//1.2.3.4:5678
        if (g_wsclient != null) {
            if (WsClient.isConnected()) {
                g_wsclient.ws_.close();
                g_wsclient = null;
            }
        }
        g_wsclient = new WsClient(`ws://${addr}`);
    }
    static isConnected() {
        return g_wsclient != null && g_wsclient.stat_;
    }
    static registProcess(protocol, func) {
        if (WsClient.isConnected()) {
            g_wsclient.func_[protocol] = func;
        }
    }
    static send(pt) {
        if (WsClient.isConnected()) {
            if (pt.offset[0] > 1024) {
                console.log("send : ", pt.offset[0])
            }
            g_wsclient.send_(pt.buffer, pt.offset[0]);
        }
    }
    static processDataQueue() {
    }
}

var g_wsclient = null;

WsClient.PROJECT_NAME = "";

WsClient.SetProjectName = function (name) {
    WsClient.PROJECT_NAME = name;
}

module.exports = {
    WsClient,
    g_wsclient,
}